사이트 내 전체검색
PHP
php 구글 캘린더, 메일 연동 방법.. 참고 자료 캘린더 api
로빈아빠
https://cmd.kr/php/813 URL이 복사되었습니다.

본문

RSS. 언제부턴가 내 생활 속으로 야금야금 침투해 들어온 녀석..

http://ko.wikipedia.org/wiki/RSS 한국어 위키의 RSS항목

우리네 웹 놀이터에서 RSS가 끼어들기 시작한지도 어언 5년이 넘은 것 같다.

물론 최근의 웹사이트들은 왠만하면 피드를 지원하고 있지만, 국내에서 사용되는 많은 사이트들(특히 대학)은 RSS? 먹는건가여 하고있는 것이 현실이다.

그래서 널리 퍼진 웹언어 php를 이용해, 소켓으로 페이지 전체 소스를 긁어와서 파싱한뒤 다시 xml형식으로 내보내는 짓을 많이들 하고 있는데..

이걸 활용하면, 구글 캘린더 api와 연동해서 문자로 간단한 알림을 받을 수 있도록 설정할 수 있다.

플레인html소스를 xml로 포팅하는 것이 그냥 커피라면, 캘린더 문자기능은 TOP (...)

html->xml 포팅을 1단계, 그 내용을 캘린더에 올리는 것을 2단계라고 한다면

작업 비중은 1단계 98%, 2단계 2% 라 하겠다-_-

이 포스트에서는 1단계는 휙휙 스킵하고, 2단계를 자세히 설명하려고 한다. 솔직히 1단계 내용은 구글링 10초만에 찾아낼 수 있는 내용들이다. 방법도 여러가지로, php용으로 개발된 파서 라이브러리를 이용하거나, 자신이 직접 정규표현식을 이용해 파싱을 진행하거나 무튼 입맛에 맞는대로 쓰면 된다.

   

1. 게시판을 rss피드로 만들기.

위에서도 말했지만, 이 내용은 휙휙 지나갈 거다..

기초적인 내용은 구글링, 아니 네이버로 검색해도 금방 얻을 수 있으므로.

캘린더 api 사용법을 보기 위해 이 포스트를 보고 있다면 이 부분은 보지 말고, 빨리 다음으로 넘어는 것이 좋다 :)

보통 게시판 내용을 피드로 만들게 되면, 게시글의 제목만을 가져오는 것이 정석이다. 왜냐하면, 소켓으로 소스 읽어오는 작업이 굉장히 느리기 때문.

내용까지 한번에 읽어올 경우 timeout될 확률이 굉장히 높다.

하지만 나는 내용까지 알고싶었다. 그래서 피드 컨텐츠 안에 게시글 내용을 모두 집어넣으려 했었다.

그런데.. 너무 느려서, 캐시가 필요했는데, 캐시는 대충 DB로 땜빵하고, 글번호 대조를 통해 새로운 글이 있으면 읽어와 db에 저장하는 방식을 택했다.

그래서 결론은, 내가 만든 피드는, 게시판 페이지 읽는 횟수가 다음과 같다는 거.

1페이지 게시글 전체 수가 N, 그 중 이미 읽어온 게시글 수가 R일 경우 읽어오는 페이지 수는 다음과 같다.

1 + (N-R)

그래서 처음 피드제작 php프로그램을 실행하게 되면 시간이 굉장히 오래 걸린다. 모든 내용을 다 긁어와서 저장하므로..

하지만 그 다음부터 피드를 읽게 되면, 게시판 1페이지 목록+새로운 글 내용만 읽어오게 된다.

   

설명을 이렇게 자세하게 하는 이유는, 구글 캘린더에 일정을 등록할 때 이 캐싱방법을 이용하기 때문이다.

121DF4264BAB475E04A874

이 그림을 보자. 마지막 4번이 동시에 일어나고 있다. php코드가 echo를 쏘면서 그와 함께 api를 이용해 캘린더에 이벤트를 등록하고 있다.

DB에 저장된 내용과 현재 게시판 내용을 비교해서 새로운 것만을 읽어와 캘린더에 등록하는 것은 나름 중요한 작업이다.

왜냐고? 안그러면 어떻게 실시간으로 캘린더에 피드를 등록하겠는가..캘린더측에서 피드를 일정에 나타내 주는 기능이 있다면 물론 이 일은 캘린더측에서 해야 맞다. 하지만 구글캘린더는 피드 삽입 기능을 지원하지 않는다. 해외 유저들도 이 부분에 불만이 많은데, 어쩔 수 없는 부분이다. 그 많은 구글 사용자가 피드를 하나씩만 등록해도 구글 서버가 얼마나 더 늘어날지 상상도 못하겠다 나는.. ㄷㄷ

 

2. 캘린더 api를 이용해 내용 등록하기.

이전에 나는 구글api를 한번도 사용해 본 적이 없다. 구글링을 통해 며칠동안 삽질한 결과 알아낸 것은

  1. 구글과 api사용자는 xml형식의 문서를 주고받으며 통신한다.
  2. 인증방법은 두 가지가 있다. AuthSub와 ClientLogin. AuthSub는 사용할때마다 End-User가 승인을 해 줘야 하므로 웹 브라우저에서 사용되는 어플리케이션에 적합하다. ClientLogin은 단지 구글 아이디와 비밀번호만 가지고 인증을 획득하므로 이 방법은 일반 어플리케이션 개발에 적합하다.
  3. API를 감싼 프레임웍이 존재한다. 가장 유명한 Zend 프레임워크는 구글의 거의 모든(?) api를 지원하고 있다.

정도..

하지만 zend를 한번 사용해 본 결과, 넘사벽에 부딪혔다. Zend api를 이용해 캘린더에 내용을 등록했더니, 한글이 깨져보였다. 포기.

구글링을 좀 더 하니, 어느 분이 블로그에 상세하게 정리해 놓은 문서가 있었다. 라이브러리도 zend보다 훨씬 가벼운 것을 사용하고 있었다.

사실 블로거가 정리했는지 기자가 정리했는지는 모르겠다. 무튼 gdataapis 라고 불리는 이 녀석은 일본사람이 작성했고.. 사용법도 간단하다.

http://www.rcdtokyo.com/etc/gdataapis/

위 링크로 가서 다운받을 수 있다. 아, 그리고 사용법은 아래 링크에서 참조바란다. 귀찮다..ㅠㅠ

http://netkong.egloos.com/373153

중간쯤부터 php를 활용해 캘린더에 일정을 등록하는 과정이 나온다. 다만 내가 여기서 설명하고자 하는 것은, 어떻게 "기본 캘린더"가 아닌 캘린더에 일정을 등록하느냐? 다.

이 따위 내용은 국내 웹에서는 찾아볼 수가 없었다. 어쨌든, 라이브러리가 예제로 제공하는 코드를 잠깐 살펴보면

  1. require_once 'Google/Calendar.php';   
  2. $entry = <<<GDATA   
  3. <entry   
  4. xmlns="http://www.w3.org/2005/Atom"  
  5. xmlns:gd="http://schemas.google.com/g/2005">   
  6. <category   
  7. scheme="http://schemas.google.com/g/2005#kind"  
  8. term="http://schemas.google.com/g/2005#event">   
  9. </category>   
  10. <title type="text">일정제목</title>   
  11. <content type="text">내용</content>   
  12. <gd:where valueString="장소">   
  13. </gd:where>   
  14. <gd:when   
  15. startTime="시작시간"  
  16. endTime="끝나는시간">   
  17. <gd:reminder minutes='1' method='sms' />   
  18. </gd:when>   
  19. </entry>   
  20. GDATA;   
  21.   
  22. $service = new Google_Calendar;   
  23. if (!$service->requestClientLogin(본인의 구글아이디,비밀번호)) {   
  24.     exit("ClientLogin has failed\n".$service->getResponseBody());   
  25. }   
  26. if (!$service->insert($entry)) {   
  27.     exit("Inserting an entry has failed\n".$service->getResponseBody());   
  28. }  
require_once 'Google/Calendar.php'; $entry = <<<GDATA <entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005"> <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/g/2005#event"> </category> <title type="text">일정제목</title> <content type="text">내용</content> <gd:where valueString="장소"> </gd:where> <gd:when startTime="시작시간" endTime="끝나는시간"> <gd:reminder minutes='1' method='sms' /> </gd:when> </entry> GDATA; $service = new Google_Calendar; if (!$service->requestClientLogin(본인의 구글아이디,비밀번호)) {     exit("ClientLogin has failed\n".$service->getResponseBody()); } if (!$service->insert($entry)) {     exit("Inserting an entry has failed\n".$service->getResponseBody()); }

정말 간단하다!! 한가지 주의할 점은 $entry를 작성할 때, 개행문자는 상관없지만 탭문자를 쓰면 알아먹질 못한다. 절대 xml 내용 안에는 탭문자를 사용하지 말자. 코드 가독성 높인다고 탭문자 쓰다가는 코드가 아예 안돌아갈 것이다.

이렇게 작성하고 실행하면, 자기 캘린더 계정에 존재하는 "기본" 캘린더에 일정이 등록된다.

하지만, 나는 "공지 전용" 캘린더를 사용하고 싶었다. 내 일정과 함께 보이는게 싫었다. 그래서 구글신께 신탁을 며칠이고 올려댔다.

그러다가 방법을 찾아 냈는데… 다음과 같이 하면 된다.

  1. if (!$service->insert($entry"http://www.google.com/calendar/feeds/[등록하고싶은 캘린더의 ID]/private/full")) {   
  2.         exit("Inserting an entry has failed\n".$service->getResponseBody());   
  3. }  
if (!$service->insert($entry, "http://www.google.com/calendar/feeds/[등록하고싶은 캘린더의 ID]/private/full")) {         exit("Inserting an entry has failed\n".$service->getResponseBody()); }

왜인지는 모르겠다. 구글 캘린더의 api를 기초부터 학습하지 않은 결과다-_-

어쨌든, 절반은 성공이다.

 

3. 구글 캘린더 문자전송 기능을 이용하기.

위의 예제 코드에서 <gd:reminder minutes='1' method='sms' />가 바로 문자알림을 설정하는 코드다.

그러니까, 웹브라우저나 RSS구독기가 내가 만든 php코드로 RSS를 요청하면, 그 php코드는 RSS를 요청자에게 건네줌과 동시에 캘린더에 3분 후에 시작될 일정으로 새로운 글의 제목을 등록한다. 

<gd:when

startTime="시작시간"

endTime="끝나는시간">

이 부분에 구글 서버의 시간 + 3분을 써주는 건데, 3분이라는 시간은 내가 정한 거고, 이건 아무렇게나 해도 된다. 5분으로 해도 되고, 새글이 등록된 후 1시간 내에 알고 싶으면 60이라고 써도 된다.

 

어떻게 SMS 알림 설정을 하는지는 "구글 캘린더 SMS" 로 검색하면 1분 안에 알 수 있다. 아, http://codepasta.net/48 을 참조해도 된다.

이 기능을 위해서 나는 구글 서버의 시간을 알아봐야 했다. 간단하게 GET을 이용해서 서버시간을 리턴하는 함수를 만들었다.

  1. function server_time($no)   
  2. {   
  3.     $fp=fsockopen("google.co.kr", 80);   
  4.     if($fp)   
  5.     {   
  6.         $gap=time();   
  7.         fputs($fp"GET / HTTP/1.0\n");   
  8.         fputs($fp,"\n");   
  9.         $data='';   
  10.         while(! feof ($fp))   
  11.         {   
  12.             $data .=fgets ($fp, 1024);   
  13.         }   
  14.         fclose ($fp);   
  15.         $data=explode("Date: "$data);   
  16.         $data=explode(" GMT"$data[1]);   
  17.         $data=strtotime($data[0]) + 9 * 3600;   
  18.         $data=(int)$data;   
  19.         if(!$data)   
  20.         {   
  21.             echo "<br />   
  22. <br />   
  23. 서버 접속에 실패하였습니다.";   
  24.         }   
  25.         else  
  26.         {   
  27.             $gap=time() - $gap;   
  28.             $data=$data + $gap;   
  29.         }   
  30.     }   
  31.     else  
  32.         echo "fp가없음";   
  33.   
  34.   
  35.     switch($no)   
  36.     {   
  37.         case 1:   
  38.         // 3분더함.   
  39.         $data+=180;   
  40.         break;   
  41.         case 2:   
  42.         $data+=180+3600;   
  43.         break;   
  44.     }      
  45.     return date("Y-m-d\TH:i:s+09:00"$data);   
  46. }  
function server_time($no) { $fp=fsockopen("google.co.kr", 80); if($fp) { $gap=time(); fputs($fp, "GET / HTTP/1.0\n"); fputs($fp,"\n"); $data=''; while(! feof ($fp)) { $data .=fgets ($fp, 1024); } fclose ($fp); $data=explode("Date: ", $data); $data=explode(" GMT", $data[1]); $data=strtotime($data[0]) + 9 * 3600; $data=(int)$data; if(!$data) { echo "<br /> <br /> 서버 접속에 실패하였습니다."; } else { $gap=time() - $gap; $data=$data + $gap; } } else echo "fp가없음"; switch($no) { case 1: // 3분더함. $data+=180; break; case 2: $data+=180+3600; break; } return date("Y-m-d\TH:i:s+09:00", $data); }

함수 호출 인자에 1을 주면 시작시간이고, 2를 주면 끝나는 시간이다.

이제 캘린더에 일정을 등록하기 위한 모든 준비가 끝났다.

게시판의 새로운 글 제목과 내용, 현재 구글 서버의 시간. 이를 토대로 내용을 잘 조합해서 insert함수를 호출하면 된다. 그러면 일정이 캘린더에 등록될 것이고, 5분 내로 폰에 문자가 올 것이다.

4. 캘린더 공유

[전컴 공지사항 문자로 받기] 항목을 조금 읽어보면, 내가 재학중인 과 구성원을 위한 포스트임을 알 수 있다. 누구나 저 포스트대로 따라만 하면 우리 과의 공지사항을 문자로 받아볼 수 있다.

이렇게 문자알림 기능을 공유하고 싶으면, public 주소를 알려주면 된다. 다른 캘린더 사용자가 public주소로 캘린더를 추가하고, SMS설정을 1분으로 해 놓으면 그사람도 똑같이 문자를 받아 볼 수 있다.

5. 피드 업데이트 주기

이 문제로 상당히 고민을 했었다. 일단 어디가 되었든, 자신이 만든 php코드를 올려놓으면, 누군가가 리더기를 통해 구독을 할 것이다.

사용자가 많아지고, 구독기의 수도 다양해지면 업데이트 주기가 빨라지고, 자연적으로 새로운 내용을 빨리 알아챌 수 있게 된다.

하지만 사용자가 기껏해야 10명 내외인 피드는 업데이트가 정말 늦다. 구글 리더만 해도 새로운 내용이 업데이트되는데 3시간정도 소요되는 듯 하다.

이는 바로 rss피드가 push가 아닌 polling방식이기 때문이다. 누군가가 내용을 요청하지 않으면, 새로운 내용을 전달해 줄리 만무하다.

업데이트가 늦어지면, 당연히 캘린더에 등록되는 시간도 늦어진다.

이를 해결하기 위해 또 며칠간 구글신께 빌고 또 빌었다. 하지만 방법은 결국 관리자가 알아서 폴링을 해야 한다.

글쎄.. 다른 방법이 존재 할 지도 모른다. 하지만 해외 유저들도 구글 리더의 업데이트 주기에 상당한 불만을 품고 있으며,

그 문제 때문에 Pubsubhubbub 라는 괴상망측한 이름의 기술도 등장한 판이다.

귀찮고, 어려워서 제대로 알아보지 않았지만, 새로운 방식으로 피드를 배달하는 방식인 것 같다.

어찌되었든, 폴링은 피드 제작자가 알아서 해야 한다. 나의 경우는 학교에서 24시간동안 동작중인 내 컴퓨터에 설치된 서버에 피드를 올려두고, 예약작업을 이용해 1분에 한번씩 폴링하도록 지시했다. 물론 php코드를 커맨드라인에서 실행하는 것이고, 이를 위해서 또 약간의 삽질을 해야만 했다..ㅠㅠ

이 문제는 정말 골치 아프다. 내가 관리하고 있는 서버가 아니면, cron 등의 스케줄러를 사용할 권한이 없기 때문에 일반적인 호스팅 서비스로는 불가능하다. 호스팅 서버에 코드를 올려두고 컴퓨터에서 1분에 한번씩 폴링을 하려면 또 하나의 프로그램을 더 사용해야 한다. 바로 RSS구독기. 피드데몬이나, 썬더버드 등을 사용해서 업데이트주기를 1분으로 하면 된다-_-

어쨌든, 이 방법은 잘 동작하고, 당분간 유지될 전망이다.

힘들더라도, 구글이 캘린더에 피드 삽입 기능을 넣어줬으면 좋겠다.

댓글목록

등록된 댓글이 없습니다.

PHP
871 (4/18P)

Search

Copyright © Cmd 명령어 3.147.55.42